package com.dayu.finecomm.protocol.hd72;

import java.util.Calendar;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dayu.finecomm.protocol.codec.Protocol;
import com.dayu.finecomm.protocol.codec.ProtocolDecoder;
import com.dayu.finecomm.protocol.pojo.TPacket;
import com.dayu.finecomm.protocol.pojo.TPacket.VType;
import com.dayu.finecomm.protocol.pojo.TSensor;

import io.netty.buffer.ByteBuf;

@Protocol(XEFEFDecoder.PROTO)
public class XEFEFDecoder extends ProtocolDecoder<TPacket> {

	static final String PROTO = "HD72";

	static final int P = 1;
	static final int K = 2;
	static final int B = 3;
	static final int A = 4;

	private static final int MAGIC = 0xEFEF;
	static Logger LOGGER = LoggerFactory.getLogger(XEFEFDecoder.class);

	@Override
	public int checkStart(ByteBuf in) {
		return 0;
	}

	@Override
	public int check(ByteBuf in) {

		if (in.readableBytes() < 18)
			return -1;

		// 协议头校验
		int c = in.readUnsignedShort();

		if (c != MAGIC) // 协议头检验
			return -1;

		int length = in.readUnsignedShort();

		if (in.readableBytes() < length + 2)// 小于length，不可能是正常报文
			return -1;

		in.skipBytes(length);

		if (in.readUnsignedShort() != 0x0d0a)
			return -1;

		/*
		 * FIXME: ACC ByteBuf b = in.slice(0, length);
		 * 
		 * // CRC校验 int acc = 0;
		 * 
		 * for (int i = 0; i < length - 3; i++) { acc = (acc +
		 * b.readUnsignedByte()) & 0xff; }
		 * 
		 * acc = (0xff & acc) ^ b.readUnsignedByte();
		 * 
		 * if (acc != 0) return -1;
		 */

		return length + 6;
	}

	@Override
	public TPacket unpack(ByteBuf in) {

		in.skipBytes(2); // AA AA
		int length = in.readUnsignedShort(); // length
		int sn = in.readUnsignedShort();

		int nYear = 2000 + com.dayu.finecomm.utils.Helpers.BCD(in.readUnsignedByte());
		int nMonth = com.dayu.finecomm.utils.Helpers.BCD(in.readUnsignedByte()) - 1;
		int nDay = com.dayu.finecomm.utils.Helpers.BCD(in.readUnsignedByte());
		int nHour = com.dayu.finecomm.utils.Helpers.BCD(in.readUnsignedByte());
		int nMinute = com.dayu.finecomm.utils.Helpers.BCD(in.readUnsignedByte());
		int nSecond = 0;

		Calendar c = Calendar.getInstance();
		c.set(nYear, nMonth, nDay, nHour, nMinute, nSecond);
		c.set(Calendar.MILLISECOND, 0);

		long sTime = c.getTime().getTime();

		TPacket s = new TPacket(VType.PPP, PROTO, sn, sTime);

		int n = in.readUnsignedByte();

		int nInterval;

		short x = in.readUnsignedByte();

		nInterval = x * 60 * 1000;
		if (nInterval == 0)
			return null;

		double v = in.readUnsignedShort();
		v /= 100;
		s.sensors.add(new TSensor("V", v, sTime));

		int h = in.readUnsignedByte();
		s.sensors.add(new TSensor("H", h, sTime));

		for (; in.readerIndex() < (length + 3);) {

			int __ = in.readUnsignedByte();

			int type = __ / 0x20;
			int no = __ % 0x20;

			// 非P、K、A、B通道
			if (type > 4 && type < 1)
				return null;

			String channel;

			switch (type) {
			case P:
				int val = Integer.reverseBytes(in.readInt());
				s.sensors.add(new TSensor("L" + no, val, sTime));
				channel = "P" + no;
				break;
			case K:
				channel = "K" + no;
				break;
			case A:
				channel = "A" + no;
				break;
			case B:
				channel = "B" + no;
				break;
			default:
				return null;
			}

			for (int i = 0; i < n; i++) {
				switch (type) {
				case P: // P通道
				{

					int val = Integer.reverseBytes(in.readInt());
					s.sensors.add(new TSensor(channel, val, sTime + nInterval * i));
				}
					break;
				case K: // K通道
				{
					int val = in.readUnsignedByte();
					val = val & 0xf;
					s.sensors.add(new TSensor(channel, val, sTime + nInterval * i));
				}
					break;
				case A:// A通道
				{
					float val = Float.intBitsToFloat(in.readInt());
					s.sensors.add(new TSensor(channel, val, sTime + nInterval * i));
				}
					break;
				case B:// B通道
				{

					int val = in.readUnsignedByte();
					val = val & 0xf;
					s.sensors.add(new TSensor(channel, val, sTime + nInterval * i));
				}
					break;

				default:
					return null;
				}
			}
		}

		return s;
	}

	@Override
	public Object timing() {
		return HD72Convention.timing();
	}

	@Override
	public byte[] echo() {
		return "@222".getBytes();
	}
}
